/***
 * @Description: 本文件主要定义的是socket编程所要实现的函数和数据结构的C语言文件
 * @Author: Liverpool
 * @Date: 2024-09-08 23:14:34
 * @LastEditTime: 2024-09-08 23:15:29
 * @LastEditors: Liverpool
 */

#include "socket.h"
#include "sock.h"
#include "MessageHander.h"
#include "debug.h"

/***
 * @description: socket接口的定义
 * @Author: Liverpool
 * @Date: 2024-09-17 22:26:12
 * @return {*} socket的接口
 * @param {int} family socket接口的协议族
 * @param {int} type 通讯的数据方式
 * @param {int} protocol 通讯的协议
 */
int x_socket(int family, int type, int protocol)
{
    D_Sock_Request req;
    req.wait = (D_Sock_Wait *)0;
    req.wait_ms = 0;
    req.sockfd = -1;
    req.create.family = family;
    req.create.type = type;
    req.create.protocol = protocol;

    net_err_t err = message_handler_func_execute(sock_create_request_in, &req);
    if (err < 0)
    {
        debug_error(Debug_SOCKET, "create socket failed.");
        return -1;
    }

    return req.sockfd;
}

/***
 * @description:socket数据发送接口
 * @Author: Liverpool
 * @Date: 2024-09-28 22:10:08
 * @return {*}
 * @param {int} socket 套接字
 * @param {void} *buf 需要发送的数据
 * @param {size_t} len 数据长度
 * @param {int} flags 发送的协议
 * @param {x_sockaddr} *dest 发送的地址
 * @param {x_socklen_t} *dest_len 地址长度
 */
ssize_t x_sendto(int socket, const void *buf, size_t len, int flags, const struct x_sockaddr *dest, x_socklen_t dest_len)
{
    // 参数检查
    if ((!buf) || (!len))
    {
        debug_error(Debug_SOCKET, " ssendto param error...");
        return -1;
    }
    if ((dest->sin_family != AF_INET) || (dest_len != sizeof(struct x_sockaddr_in)))
    {
        debug_error(Debug_SOCKET, " ssendto param error...");
        return -1;
    }
    // 发送工作线程的API参数赋值
    ssize_t send_size = 0;
    uint8_t *start = (uint8_t *)buf;
    while (len > 0) // 循环发送
    {
        D_Sock_Request req;
        req.wait = (D_Sock_Wait *)0;
        req.wait_ms = 0;
        req.sockfd = socket;
        req.data.buf = start;
        req.data.len = len;
        req.data.flags = flags;
        req.data.addr = (struct x_sockaddr *)dest;
        req.data.addr_len = &dest_len;
        req.data.comp_len = 0;

        net_err_t err = message_handler_func_execute(sock_sendto_request_in, &req);
        if (err < 0)
        {
            debug_error(Debug_SOCKET, "send socket failed.");
            return -1;
        }
        if (req.wait && ((err = sock_wait_entry(req.wait, req.wait_ms)) < 0))
        {
            debug_error(Debug_SOCKET, "send failed.");
            return -1;
        }
        len -= req.data.comp_len;
        start += req.data.comp_len;
        send_size += (ssize_t)req.data.comp_len;
    }
    return send_size;
}

/***
 * @description: sokcet接口的数据接收接口
 * @Author: Liverpool
 * @Date: 2024-10-04 15:50:20
 * @return {*}
 * @param {int} socket socket套接字地址
 * @param {void} *buf 接收的数据地址
 * @param {size_t} len 接收的数据缓冲区大小
 * @param {int} flags 标志位
 * @param {x_sockaddr} *src 接收地址
 * @param {x_socklen_t} src_len接收地址的长度
 */
ssize_t x_recvfrom(int socket, void *buf, size_t len, int flags, const struct x_sockaddr *src, x_socklen_t *src_len)
{
    // 参数检查
    if (!buf || !len || !src)
    {
        debug_error(Debug_SOCKET, "recvform param error...");
        return -1;
    }
    while (1)
    {
        D_Sock_Request req;
        req.wait = (D_Sock_Wait *)0;
        req.wait_ms = 0;
        req.sockfd = socket;
        req.data.buf = (uint8_t *)buf;
        req.data.len = len;
        req.data.flags = flags;
        req.data.addr = (struct x_sockaddr *)src;
        req.data.addr_len = src_len;
        req.data.comp_len = 0;
        net_err_t err = message_handler_func_execute(sock_recvfrom_request_in, &req);
        if (err < 0)
        {
            debug_error(Debug_SOCKET, "receive from socket failed.");
            return -1;
        }
        if (req.data.comp_len)
        {
            return (ssize_t)req.data.comp_len;
        }
        err = sock_wait_entry(req.wait, req.wait_ms);
        if (err < 0)
        {
            debug_error(Debug_SOCKET, "receive failed.");
            return -1;
        }
    }
}

/***
 * @description: 设置sokcet套接字选项
 * @Author: Liverpool
 * @Date: 2024-10-09 00:30:15
 * @return {*}
 * @param {int} socket socket套接字地址
 * @param {int} level 选项级别
 * @param {int} optname 选项名称
 * @param {char} *optval 选项数据内容
 * @param {int} len 选项数据内存大小
 */
int x_setsockopt(int socket, int level, int optname, const char *optval, int len)
{
    if (!optval || !len)
    {
        debug_error(Debug_SOCKET, "recvform param error...");
        return -1;
    }
    D_Sock_Request req;
    req.wait = (D_Sock_Wait *)0;
    req.wait_ms = 0;
    req.sockfd = socket;
    req.opt.level = level;
    req.opt.optname = optname;
    req.opt.optval = optval;
    req.opt.len = len;
    net_err_t err = message_handler_func_execute(sock_setsockopt_request_in, &req);
    if (err < 0)
    {
        debug_error(Debug_SOCKET, "set socket opt failed.");
        return -1;
    }
    return err;
}